/* Castle of the Winds style Inventory manipulation
	by Shadowdarke (shadowdarke@byond.com)
*/

var
	obj/inv_close_button/inv_close_button = new()

mob
	var
		// associated list of equiped items indexed by slot
		list/inv_equipped = list()

		tmp
			list/inv_panels = list()	// open panels indexed obj

	Stat()
		..() // append this to other panel defined elsewhere
		// make sure the client eye is on the Inventory
		if(!client) return
		var/turf/T = client.eye
		if(!istype(T) || (T.tag != "inv_center")) return

		if(statpanel("Floor"))
			for(var/obj/object/O in oview(1,src))
				stat(O)



		for(var/obj/object/O in inv_panels)

			if(statpanel("Purse"))
				var/obj/object/Container/Purse/P = src.inv_equipped["purse"]
				if(P)
					for (var/V in P.Casharray)
						var/i = P.Casharray[V]
						stat( "[V] - [i]")

				stat("")

			if(statpanel(O.name))
				O.inv_header()
				stat(O.contents)

obj

	object
		var
			weight = 0
			max_weight = 0	// only used for containers
			bulk = 0
			max_bulk = 0	// only used for containers
			fixed_bulk = 0
			inv_slot		// where it is equipped

		proc
			inv_equip(mob/M, slot)
				src.CreateName(0,0,0)
				M << "You equip the [src] in your [slot]"
				..()
				// called when M equips this obj in "slot"
				// override for specific objs

			inv_unequip(mob/M, slot)
				src.RemoveName()
				..()
				// called when M unequips this obj in "slot"
				// override for specific objs

			inv_header()
				// may override for different container headers
				stat("Wt [weight] ([max_weight])   \
					Bulk [bulk] ([max_bulk])")
				stat(inv_close_button)
/*
			inv_updateslot(mob/M, slot)
				// get the originating equip slot to update it
				spawn(1)
					var/turf/inv_slot/S
					for(S in range(world.view,locate("inv_center")))
						if(S.name == slot)
							S.inv_update(M)
							inv_unequip(M,S.name)
							screen_loc = ""
							var/client/C = M.client
							if(C)
								C.screen -= src
							break
	*/
		DblClick()
			if(loc != usr) return
			if(max_weight)
				usr.inv_panels += src
				usr.client.statpanel = name

		Enter(A)
			// block if it is an obj that is too heavy or bulky
			if(A==src) return
			if(istype(A,/obj/object))
				var/obj/object/O = A
				if((weight + O.weight) > max_weight) return 0
				if(!fixed_bulk)
					if((bulk + O.bulk) > max_bulk) return 0
			return ..()

		Entered(A)
			if(istype(A,/obj/object))
				var/obj/object/O = A
				weight += O.weight
				if(!fixed_bulk)
					bulk += O.bulk

		Exited(A)
			if(istype(A,/obj/object))
				var/obj/object/O = A
				weight -= O.weight
				if(!fixed_bulk)
					bulk -= O.bulk

		MouseDrop(over,src_loc,over_loc)
			Fake_MouseDrop(over,src_loc,over_loc)

		proc/Fake_MouseDrop(over,src_loc,over_loc) // so it can be called manually

// over seems to be the object to go in
// over_loc seems to the be the inv_slot
//


			var/new_slot = null
			var/new_loc = null
			var/turf/inv_slot/T

			if(istype(over,/obj/object))
				var/obj/object/O = over
				if(O.max_weight && !isturf(O.loc))
					new_loc = O
/*
					if(Move(O))
						usr.inv_equipped -= inv_slot
						inv_slot = null
					return
*/
			else if(istype(over_loc, /turf/inv_slot))
				T = over_loc
				if(T.name == "floor")
					over_loc = "Floor"
					// handle it as if dropped on floor panel
				else
					if(usr.inv_equipped[T.name])
						var/obj/object/O = usr.inv_equipped[T.name]
						if(O.max_weight && !isturf(O.loc))
							new_loc = O
/*
							if(Move(O))
								usr.inv_equipped -= inv_slot
								inv_slot = null
							return
*/
						else
							usr << "You already have [O] equipped as \
								your [T.name]."

					else if(T.inv_allow(src) && Move(usr))
						new_loc = usr
						new_slot = T.name
						/*
						usr.inv_equipped[T.name] = src
						inv_slot = T.name
						inv_equip(usr, T.name)

					T.inv_update(usr)
					return
					*/

			else if(istext(over_loc))
				if(over_loc == "Floor")
					new_loc = usr.loc // drop
					/*
					Move(usr.loc)
					usr.inv_equipped -= inv_slot
					inv_slot = null
					usr.inv_panels -= src
					*/
				else
					for(var/obj/object/O in usr.inv_panels) // if its a bag
						if(over_loc == O.name) // move it there
							new_loc = O
							/*
							if(Move(O))
								usr.inv_equipped -= inv_slot
								inv_slot = null
							*/

			if(new_loc && Move(new_loc))
				usr.inv_equipped -= inv_slot
				if(inv_slot)
					inv_unequip(usr,inv_slot)
				inv_slot = new_slot
				screen_loc = ""
				var/client/C = usr.client
				if(C)
					C.screen -= src
				if(new_loc == usr)
					usr.inv_equipped[T.name] = src // means that the usr's equipped list is updated so that the item indexed by "slotname" = src
					inv_slot = T.name //lets the obj know which inventory slot it's in
					inv_equip(usr, T.name) // Maz stuff
					T.inv_update(usr) // tells the inventory slot to update it's display of itself to usr

				else
					usr.inv_panels -= src

		proc/Force_equip(var/mob/M, var/T as text)
			M.inv_equipped[T] = src // means that the usr's equipped list is updated so that the item indexed by "slotname" = src
			inv_slot = T //lets the obj know which inventory slot it's in
			inv_equip(M, T) // Maz stuff

	inv_close_button
		icon = 'inventory.dmi'
		name = "close this container"


		Click(Loc)
			for(var/obj/O in usr.inv_panels)
				if(usr.client.statpanel == O.name)
					usr.inv_panels -= O
					break

obj
	placeholder
		proc/CreateName(r=0, g=r, b=r)
			overlays = list()
			var/lines = round(32 / namefont.height)
			var/txt = namefont.GetLines(name, width = 96, maxlines = lines,\
			                            flags = DF_WRAP_ELLIPSIS)
			var/size = namefont.RoundUp32(namefont.GetWidth(txt))
			var/iconset/s = namefont.DrawText(txt, size / 2, 0,\
			                    width = size, maxlines = lines,\
			                    flags = DF_JUSTIFY_CENTER | DF_WRAP_ELLIPSIS,\
			                    icons_x = size / 32, icons_y = 1)
			s.Transparent()     // white text on transparent background
			if(r<255 || g<255 || b<255)
				s.Blend(rgb(r, g, b), ICON_MULTIPLY)
			var/obj/O = new
			O.pixel_y = -32
			for(var/xx = 0, xx < s.w, ++xx)
				var/icon/ic = s.GetIcon(xx, 0)
				if(ic)
					O.icon = ic
					O.pixel_x = (xx + (1 - s.w) / 2) * 32
					overlays += O
			del(O)
		proc/RemoveName()
			for(var/v in overlays)
				overlays -= v
		Del()
			RemoveName()
			..()

		DblClick()
			var/layout
			layout += "{ [src.name] - [src] }<br> "
			for(var/v in src.vars)
				layout +=  "[v] - [vars[v]]<br>"
			world << browse(layout)

turf
	inv_slot	// inventory slots
		proc
			inv_allow(obj/O)
				// override to allow onlw specific objects in this slot
				return 1

			inv_update(mob/M)
				var/client/C = M.client
				if(!C) return
				var/obj/O = M.inv_equipped[name]

				if(O) //if something is there

					//below seems to be where it doesnt work.

					if(istype(O,/obj/placeholder)) //is it just the default text (Nothing therefore)
						var/obj/placeholder/Z = locate("[M]-[src.name]")
						world << {"locate("[M]-[src.name]")"}
						world << "[Z]"
						del Z
					var/turf/Center = locate("inv_center")
					var/X = x - Center.x + world.view + 1
					var/Y = y - Center.y + world.view + 1
					O.screen_loc = "[X],[Y]"
					C.screen += O

// add a placeholder obj with the name of the slot.
				else
					var/obj/placeholder/P = new
					var/turf/Center = locate("inv_center")
					var/X = x - Center.x + world.view + 1
					var/Y = y - Center.y + world.view + 1
					P.screen_loc = "[X],[Y]"
					P.name = src.name
					P.CreateName(120,120,120)
					P.tag = "[M]-[src.name]"
					world << {"locate("[M]-[src.name]")"}
					C.screen += P

		DblClick()
			var/obj/object/O = usr.inv_equipped[name]
			if(O) O.DblClick()
/*
		MouseDrop(over,src_loc,over_loc)
			var/obj/object/O = usr.inv_equipped[name]
			if(O) O.MouseDrop(over,src_loc,over_loc)
*/
		close
			icon = 'inventory.dmi'
			icon_state = "x"

			Click()
				var/mob/pc/I = usr
				I.inventory()


			inv_allow(obj/O)
				return 0 // no obj's in close anymore :)

		proc/CreateName(r=0, g=r, b=r)
			overlays = list()
			var/lines = round(32 / namefont.height)
			var/txt = namefont.GetLines(name, width = 96, maxlines = lines,\
			                            flags = DF_WRAP_ELLIPSIS)
			var/size = namefont.RoundUp32(namefont.GetWidth(txt))
			var/iconset/s = namefont.DrawText(txt, size / 2, 0,\
			                    width = size, maxlines = lines,\
			                    flags = DF_JUSTIFY_CENTER | DF_WRAP_ELLIPSIS,\
			                    icons_x = size / 32, icons_y = 1)
			s.Transparent()     // white text on transparent background
			if(r<255 || g<255 || b<255)
				s.Blend(rgb(r, g, b), ICON_MULTIPLY)
			var/obj/O = new
			O.pixel_y = -32
			for(var/xx = 0, xx < s.w, ++xx)
				var/icon/ic = s.GetIcon(xx, 0)
				if(ic)
					O.icon = ic
					O.pixel_x = (xx + (1 - s.w) / 2) * 32
					overlays += O
			del(O)
		proc/RemoveName()
			for(var/v in overlays)
				overlays -= v



// The actual slots for the objects

turf/inv_slot
	icon = 'inventory.dmi'
	icon_state = "8"

	DblClick()
		var/layout
		layout += "{ [src.name] - [src] }<br> "
		for(var/v in src.vars)
			layout +=  "[v] - [vars[v]]<br>"
		world << browse(layout)


	armor
		inv_allow(obj/O)
			// allow only /obj/armor
			if(istype(O,/obj/object/Armor)) return 1

	ring
		inv_allow(obj/O)
			// allow only /obj/ring in either of these slots
			if(istype(O,/obj/object/Ring)) return 1

		right_ring

	pack
		inv_allow(obj/O)
			// allow only /obj/object/pack
			if(istype(O,/obj/object/Container)) return 1

	shield
		inv_allow(obj/O)
			// allow only /obj/object/pack
			if(istype(O,/obj/object/Shield)) return 1

	gauntlets
		inv_allow(obj/O)
			// allow only /obj/object/pack
			if(istype(O,/obj/object/Gauntlets)) return 1

	helmet
		inv_allow(obj/O)
			// allow only /obj/object/pack
			if(istype(O,/obj/object/Helmet)) return 1

	cloak
		inv_allow(obj/O)
			// allow only /obj/object/pack
			if(istype(O,/obj/object/Cloak)) return 1

	neckware
		inv_allow(obj/O)
			// allow only /obj/object/pack
			if(istype(O,/obj/object/Neckware)) return 1

	bracers
		inv_allow(obj/O)
			// allow only /obj/object/pack
			if(istype(O,/obj/object/Bracers)) return 1

	weapon
		inv_allow(obj/O)
			// allow only /obj/object/pack
			if(istype(O,/obj/object/Weapon)) return 1

	belt
		inv_allow(obj/O)
			// allow only /obj/object/pack
			if(istype(O,/obj/object/Container)) return 1

	boots
		inv_allow(obj/O)
			// allow only /obj/object/pack
			if(istype(O,/obj/object/Boots)) return 1

	purse
		inv_allow(obj/O)
			// allow only /obj/object/pack
			if(istype(O,/obj/object/Container/Purse)) return 1

	free_hand
		inv_allow(obj/O)
			// allow only /obj/object/pack
			if(istype(O,/obj/object/)) return 1